package org.example.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;


/**
 * @ Author     ：hanxi
 * @ Date       ：Created in 23:04 2024/3/13
 * @ Description：
 */
@Slf4j
public class RSA {
    //定义加密方式
    public static final String KEY_RSA = "RSA";
    //定义签名算法
    private final static String KEY_RSA_SIGNATURE = "MD5withRSA";

    /**
     * 生成公私密钥对
     */
    public static void init() throws NoSuchAlgorithmException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(KEY_RSA);
        //设置密钥对的bit数，越大越安全，但速度减慢，一般使用512或1024
        generator.initialize(1024);
        KeyPair keyPair = generator.generateKeyPair();
        // 获取公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 获取私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        String publicKeyStr = RSA.getPublicKey(publicKey);
        String privateKeyStr = RSA.getPrivateKey(privateKey);
        System.out.println("公钥:"+ publicKeyStr);
        System.out.println("私钥:"+ privateKeyStr);
    }

    /**
     * 获取Base64编码的公钥字符串
     */
    public static String getPublicKey(RSAPublicKey publicKey) {
        String str = "";
        Key key = (Key) publicKey;
        str = encryptBase64(key.getEncoded());
        return str;
    }

    /**
     * 获取Base64编码的私钥字符串
     */
    public static String getPrivateKey(RSAPrivateKey privateKey) {
        String str = "";
        Key key = (Key) privateKey;
        str = encryptBase64(key.getEncoded());
        return str;
    }

    /**
     * BASE64 解码
     *
     * @param key 需要Base64解码的字符串
     * @return 字节数组
     */
    public static byte[] decryptBase64(String key) {
        return Base64.getDecoder().decode(key);
    }

    /**
     * BASE64 编码
     *
     * @param key 需要Base64编码的字节数组
     * @return 字符串
     */
    public static String encryptBase64(byte[] key) {
        return new String(Base64.getEncoder().encode(key));
    }

    /**
     * 公钥加密
     *
     * @param encryptingStr
     * @param publicKeyStr
     * @return
     */
    public static String encryptByPublic(String encryptingStr,String publicKeyStr) {
        try {
            // 将公钥由字符串转为UTF-8格式的字节数组
            byte[] publicKeyBytes = decryptBase64(publicKeyStr);
            // 获得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
            // 取得待加密数据
            byte[] data = encryptingStr.getBytes("UTF-8");
            KeyFactory factory;
            factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            // 返回加密后由Base64编码的加密信息
            return encryptBase64(cipher.doFinal(data));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }


    /**
     * 私钥解密
     *
     * @param encryptedStr
     * @param privateKeyStr
     * @return
     */
    public static String decryptByPrivate(String encryptedStr,String privateKeyStr) {
        try {
            // 对私钥解密
            byte[] privateKeyBytes = decryptBase64(privateKeyStr);
            // 获得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            // 获得待解密数据
            byte[] data = decryptBase64(encryptedStr);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // 返回UTF-8编码的解密信息
            return new String(cipher.doFinal(data), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    /**
     * 私钥加密
     *
     * @param encryptingStr
     * @param privateKeyStr
     * @return
     */
    public static String encryptByPrivate(String encryptingStr,String privateKeyStr) {
        try {
            byte[] privateKeyBytes = decryptBase64(privateKeyStr);
            // 获得私钥
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            // 取得待加密数据
            byte[] data = encryptingStr.getBytes("UTF-8");
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PrivateKey privateKey = factory.generatePrivate(keySpec);
            // 对数据加密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            // 返回加密后由Base64编码的加密信息
            return encryptBase64(cipher.doFinal(data));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    /**
     * 公钥解密
     *
     * @param encryptedStr
     * @param publicKeyStr
     * @return
     */
    public static String decryptByPublic(String encryptedStr,String publicKeyStr) {
        try {
            // 对公钥解密
            byte[] publicKeyBytes = decryptBase64(publicKeyStr);
            // 取得公钥
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
            // 取得待加密数据
            byte[] data = decryptBase64(encryptedStr);
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            PublicKey publicKey = factory.generatePublic(keySpec);
            // 对数据解密
            Cipher cipher = Cipher.getInstance(factory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            // 返回UTF-8编码的解密信息
            return new String(cipher.doFinal(data), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }

        return "";
    }

    /**
     * 用私钥对加密数据进行签名
     *
     * @param encryptedStr
     * @param privateKeyStr
     * @return
     */
    public static String sign(String encryptedStr,String privateKeyStr) {
        String str = "";
        try {
            //将私钥加密数据字符串转换为字节数组
            byte[] data = encryptedStr.getBytes();
            // 解密由base64编码的私钥
            byte[] bytes = decryptBase64(privateKeyStr);
            // 构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs = new PKCS8EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取私钥对象
            PrivateKey key = factory.generatePrivate(pkcs);
            // 用私钥对信息生成数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initSign(key);
            signature.update(data);
            str = encryptBase64(signature.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 校验数字签名
     *
     * @param encryptedStr
     * @param sign
     * @param publicKeyStr
     * @return 校验成功返回true，失败返回false
     */
    public static boolean verify(String encryptedStr, String sign,String publicKeyStr) {
        boolean flag = false;
        try {
            //将私钥加密数据字符串转换为字节数组
            byte[] data = encryptedStr.getBytes();
            // 解密由base64编码的公钥
            byte[] bytes = decryptBase64(publicKeyStr);
            // 构造X509EncodedKeySpec对象
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
            // 指定的加密算法
            KeyFactory factory = KeyFactory.getInstance(KEY_RSA);
            // 取公钥对象
            PublicKey key = factory.generatePublic(keySpec);
            // 用公钥验证数字签名
            Signature signature = Signature.getInstance(KEY_RSA_SIGNATURE);
            signature.initVerify(key);
            signature.update(data);
            flag = signature.verify(decryptBase64(sign));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }


//    public static void main(String[] args) {
//        try {
//            init();
//        } catch (NoSuchAlgorithmException e) {
//            e.printStackTrace();
//        }
//    }

    public static void main(String[] args) {
        String publicKey= "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeWrhwPapSwFefbup538VFmm0nhkHNSOC40e3XvjDGkRdMxKWMBJfJQ9GhMvxAj0ZPp3Ujdsfx0Zqm2+n9bsAX2yWtdAez2MiVfA7leSLV9JaX68GNlWl2s3G6ETj55RXVeI8tUN7bcFRXUvc6ggqM1YjtVvTKt6zfFjdvZA348wIDAQAB";
//        String json = "{}";
//        String decrypt =RSA.encryptByPublic(json,publicKey);
      String decrypt ="ZjWGR4RYhbQ1In1JVtCWINQRsG6cc9OOZz7/59ktn3WL/BzA608nQX2fmsJy8cDifkigpERvewimY7yxSLJu+muuR+LwFnTeCCZcQMVyYuKle8JDM6EBXB/Yytt/MjbkJSb+/bocMovrdUn+ys02+lJeVFvoWFDc5bC58z8/QoQ=";
        System.out.println(decrypt);
        try {
            String md5 = MD5Signature.sign(decrypt, "abaReO9zIZcxPZIMg02Lt3");
            System.out.println(md5);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String privateKey= "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJ5auHA9qlLAV59u6nnfxUWabSeGQc1I4LjR7de+MMaRF0zEpYwEl8lD0aEy/ECPRk+ndSN2x/HRmqbb6f1uwBfbJa10B7PYyJV8DuV5ItX0lpfrwY2VaXazcboROPnlFdV4jy1Q3ttwVFdS9zqCCozViO1W9Mq3rN8WN29kDfjzAgMBAAECgYEAiNtfC6I/0cTp9aCmhS4gEEemjsI5nHGfxhuoswxsmzBKMs7BRIGzrP4v7mFiIWmyGqVfV4cQxq2gOxVU5PMSkC0qNsNQ9H+H2d6opCS3yHVhQ22OqUZ/RWAWrKLCoQ3yxCEGgeAJvdSDtHRgdavvIhh5dvbRVbLjJ811+ZSoZgECQQDiaFc2Ft47oKgORRPJJsRJtcAJghjQFc2sRvBaifp0E/YGLyusQYgwZJwLXnPW7Z1liGYqeBAv+JqOmNNg7kC1AkEAsw1NEaXzn3yRRLOIcWCHe9Ql6yIjGjAG5cZa9F9uu9Zmu8zm2zu1LIx5Etsd+HhHoQ15pjsCP7WX6GORQuXkBwJAO3DVZLgARHtbY9Oy7B6nbgqvjk9/oDH5O3+sXrjW7l7HOrxrpN/Xl4zygvGbTBQ6PIvg9slqxo1oVoO9CzfB+QJAFe15FMI4Fb4RpFJAUXI65WVTx3oExn4/OgCSvv649vQI3NL5KrwjMfN6GF8RSo6gZw7ZaQws+FRq6CDZd1HkHQJAL6uEHMO9B9dyYLuK6tAVxIlh9qzGyCsR0A0gCYZY++uSYN/ACjTyyxz2rW/gPSdUaJ+Di2d6X94FDCofVX6FGw==";
        String s = RSA.decryptByPrivate(decrypt, privateKey);
        System.out.println(s);
        JSONObject jsonObject = JSON.parseObject(s);
    }
}
